﻿using System;
using System.Windows.Input;
using WindowsPhoneMvp.Navigation;

namespace WindowsPhoneMvp.Commands
{
    /// <summary>
    /// An ICommand that will navigate to a view
    /// </summary>
    public sealed class NavigationCommand : ICommand
    {
        internal Func<bool> InternalCanExecute;
        private readonly string view;
        internal NavigationData NavigationData;
        internal Action PreNavigationAction;
        public INavigationService NavigationService { get; private set; }

        public NavigationCommand(string view, 
            INavigationService navigationService,
            NavigationData navigationData = null,
            Action preNavigationAction = null,
            Func<bool> canExecute = null)
        {
            this.view = view;
            InternalCanExecute = canExecute;
            NavigationData = navigationData;
            PreNavigationAction = preNavigationAction;
            NavigationService = navigationService;

            if (NavigationData == null)
                NavigationData = new NavigationData(view);
        }

        private void ExecuteInternal()
        {
            if (PreNavigationAction != null) PreNavigationAction();
            NavigationService.ToView(view, x => {
                                                  foreach(var p in NavigationData.Parameters)
                                                    x.Parameters.Add(p);
                                                });
        }

        public bool CanExecute(object parameter)
        {
            if (InternalCanExecute == null)
            {
                return true;
            }
            return InternalCanExecute();
        }

        public void Execute(object parameter)
        {
            ExecuteInternal();
        }

        public event EventHandler CanExecuteChanged;

        private void OnCanExecuteChanged(EventArgs e)
        {
            var canExecuteChanged = CanExecuteChanged;

            if (canExecuteChanged != null)
                canExecuteChanged(this, e);
        }

        public void RaiseCanExecuteChanged()
        {
            OnCanExecuteChanged(EventArgs.Empty);
        }
    }
}
